﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Scriptor.Presentation.Core;
using System.IO;
using Scriptor.Presentation.Entity;
using Scriptor.Presentation.Templates;
using Scriptor.Presentation.Enumerator;
using System.Xml;
using System.Reflection;

namespace Scriptor.Presentation
{
    public partial class frmWizard : Form
    {
        public frmWizard()
        {
            InitializeComponent();
        }

        public string OldInterface { get; set; }
        public Method mtd { get; set; }

        public List<string> listaInterface { get; set; }
        public List<Method> listaExterna { get; set; }

        public List<Entidade> listaEntidade { get; set; }
        public List<Enumeradores> lstEnumerators { get; set; }

        private void InterfaceCad_Load(object sender, EventArgs e)
        {
            this.tvList.Nodes.Add("Interface", "Interface");
            listaExterna = new List<Method>();

            LoadReturnSource();
            LoadParamNameSource();
            LoadParamTypeSource();
        }

        private void LoadParamTypeSource()
        {
            AutoCompleteStringCollection listaInterna = new AutoCompleteStringCollection();

            if (listaExterna != null)
            {

                this.listaExterna.ForEach(delegate(Method mtd)
                {
                    foreach (Param param in mtd.ParamList)
                    {
                        string tipo = param.ParameterType;
                        if(!string.IsNullOrEmpty(tipo) && !listaInterna.Contains(tipo))
                            listaInterna.Add(tipo);
                    }
                }
                );

                cbTypeParametroMetodo.AutoCompleteCustomSource = listaInterna;
            }
        }

        private void LoadParamNameSource()
        {
            AutoCompleteStringCollection listaInterna = new AutoCompleteStringCollection();

            if (listaExterna != null)
            {

                this.listaExterna.ForEach(delegate(Method mtd)
                {
                    foreach (Param param in mtd.ParamList)
                    {
                        string name = param.ParameterName;
                        if (!string.IsNullOrEmpty(name) && !listaInterna.Contains(name))
                            listaInterna.Add(name);
                    }
                }
                );

                cbNameParametroMetodo.AutoCompleteCustomSource = listaInterna;
            }
        }

        private void LoadReturnSource()
        {
            AutoCompleteStringCollection listaInterna = new AutoCompleteStringCollection();

            if (listaEntidade != null)
            {
                this.listaEntidade.ForEach(delegate(Entidade ent)
                {
                    if (ent.Sentido == Enums.Direction.Saida)
                        listaInterna.Add(ent.NomeEntidade);
                }
                );

                cbRetornoMetodo.AutoCompleteCustomSource = listaInterna;
            }
        }

        private void btnAddInterface_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtInterface.Text))
                return;

            if (txtInterface.Text.IndexOf("Sinacor.Servico") != -1)
            {
                AddInterface(txtInterface.Text);
            }
            else
            {
                if (txtInterface.Text.Substring(0, 1) != "I" || txtInterface.Text.Substring(1, 1) != txtInterface.Text.Substring(1, 1).ToUpper())
                {
                    MessageBox.Show("Nomenclatura de Interface fora do padrão estabelecido.", "Erro");
                    txtInterface.Text = string.Empty;
                    txtInterface.Focus();
                    return;
                }
                else
                {
                    if (!string.IsNullOrEmpty(txtInterface.Text) && !string.IsNullOrEmpty(txtModulo.Text) && !string.IsNullOrEmpty(txtSubModulo.Text))
                        AddInterface(txtInterface.Text);
                }
            }
        }

        private void AddInterface(string pInterface)
        {
            if (string.IsNullOrEmpty(this.OldInterface))
            {
                string strInterface = @"Sinacor.Servico.{0}.{1}.Service.ServiceContract.";

                strInterface = string.Format(strInterface, txtModulo.Text, txtSubModulo.Text);

                strInterface += pInterface;

                if (tvList.Nodes[0].Nodes[strInterface] == null)
                {
                    TreeNodeCollection tnC = tvList.Nodes[0].Nodes;

                    foreach (TreeNode node in tnC)
                    {
                        if (node.BackColor == Color.Yellow)
                            node.BackColor = Color.Transparent;
                    }

                    bool AlterouModuloSubModulo = false;

                    if (tvList.Nodes[0].GetNodeCount(true) != 0)
                    {
                        string[] toCompare = tvList.Nodes[0].Nodes[0].Text.Split('.');
                        string[] newInterface = strInterface.Split('.');

                        if (toCompare[2] != newInterface[2] || toCompare[3] != newInterface[3])
                            AlterouModuloSubModulo = true;

                    }

                    if (!AlterouModuloSubModulo)
                    {
                        tvList.Nodes[0].Nodes.Add(strInterface, strInterface);

                        if (this.listaInterface == null)
                            listaInterface = new List<string>();

                        this.listaInterface.Add(strInterface);
                        tvList.Nodes[0].Nodes[strInterface].BackColor = Color.Yellow;
                        tvList.Nodes[0].Expand();
                        txtInterface.Text = string.Empty;
                        txtMethodName.Focus();
                    }
                    else
                        MessageBox.Show("O Módulo ou Sub-Modulo foram alterados." + Environment.NewLine + "Verifique", "Erro");
                }
                else
                {
                    if (string.IsNullOrEmpty(OldInterface))
                    {
                        MessageBox.Show("Interface já cadastrada.", "Erro");
                        txtInterface.SelectAll();
                        txtInterface.Focus();
                        return;
                    }



                }
            }
            else
            {

                bool AlterouModuloSubModulo = false;

                if (tvList.Nodes[0].GetNodeCount(true) != 0)
                {
                    string[] toCompare = tvList.Nodes[0].Nodes[0].Text.Split('.');
                    string[] newInterface = txtInterface.Text.Split('.');

                    if (toCompare[2] != newInterface[2] || toCompare[3] != newInterface[3])
                        AlterouModuloSubModulo = true;

                }

                if (!AlterouModuloSubModulo)
                {
                    TreeNodeCollection tnC = tvList.Nodes[0].Nodes;

                    foreach (TreeNode node in tnC)
                    {
                        if (node.Text == OldInterface)
                        {
                            node.Text = txtInterface.Text;
                            node.Name = txtInterface.Text;
                        }
                    }

                    this.listaInterface[this.listaInterface.IndexOf(OldInterface)] = txtInterface.Text;

                    /*Grupo Alterar Interface*/
                    btnCadIntCancel.Visible = false;
                    txtModulo.Enabled = true;
                    txtSubModulo.Enabled = true;

                    groupMethods.Enabled = true;
                    groupListMethods.Enabled = true;

                    this.txtInterface.Text = string.Empty;
                    this.OldInterface = string.Empty;
                }
                else
                    MessageBox.Show("O Módulo ou Sub-Modulo foram alterados." + Environment.NewLine + "Verifique", "Erro");
            }
        }
        

        private void btnAddMetodo_Click(object sender, EventArgs e)
        {
            string ActiveNode = string.Empty;
            TreeNodeCollection tnC = tvList.Nodes[0].Nodes;

            foreach (TreeNode node in tnC)
            {
                if (node.BackColor == Color.Yellow)
                {
                    ActiveNode = node.Text;
                }
            }

            if (string.IsNullOrEmpty(txtMethodName.Text))
            {
                MessageBox.Show("Informe o nome do Metodo", "Informe o nome do Metodo");
                return;
            }
            else
                if (string.IsNullOrEmpty(ActiveNode))
                {
                    MessageBox.Show("Ative a Interface", "Ative a Interface");
                    return;
                }
                else
                {
                    AddMethod(ActiveNode, txtMethodName.Text,
                                    cbRetornoMetodo.Text, rbRetornoList.Checked,
                                    listParams.Nodes[0].Nodes,
                                    txtComentarioMetodo.Text);
                }
        }

        private void AddMethod(string pInterface, string pMethodName,
                                string pRetornoName, bool pRetornoList,
                                TreeNodeCollection paramList, string pCommentName)
        {
            string retornoFormatado = @"Sinacor.Servico.{0}.{1}.Service.DataContract.Response.{2}Response";

            if (pRetornoName == string.Empty)
                retornoFormatado = "void";
            else
            {
                if (pRetornoList)
                {
                    retornoFormatado = "List<" + string.Format(retornoFormatado, txtModulo.Text, txtSubModulo.Text, pRetornoName) + ">";
                }
                else
                {
                    retornoFormatado = string.Format(retornoFormatado, txtModulo.Text, txtSubModulo.Text, pRetornoName);
                }
            }

            string MethodSignature;

            MethodSignature = retornoFormatado + " " + pMethodName + "(";

            foreach (TreeNode node in paramList)
            {
                string aux = node.Text.Replace("parameter - ", "");

                if (aux.IndexOf(" ") != -1)
                {
                    aux = aux.Substring(0, aux.IndexOf(" ")) + aux.Substring(aux.IndexOf(" ")).ToLower();
                }

                MethodSignature += aux;
                MethodSignature += ", ";
            }

            if(paramList.Count != 0)
                MethodSignature = MethodSignature.Substring(0, MethodSignature.Length - 2);

            MethodSignature += ")";

            if (mtd == null)
            {
                if (this.tvList.Nodes[0].Nodes[pInterface].Nodes[MethodSignature] == null)
                {
                    this.tvList.Nodes[0].Nodes[pInterface].Nodes.Add(MethodSignature, MethodSignature);

                    this.tvList.Nodes[0].Nodes[pInterface].ExpandAll();

                    //INFO

                    mtd = new Method();

                    mtd.MethodName = pMethodName;
                    mtd.ReturnName = pRetornoName;
                    mtd.ReturnIsList = pRetornoList;
                    mtd.ParamList = this.GeraListaParams(paramList);
                    mtd.MethodComent = pCommentName;
                    mtd.MethodSignature = MethodSignature;

                    this.tvList.Nodes[0].Nodes[pInterface].Nodes[MethodSignature].Tag = mtd;

                    if (listaExterna == null) listaExterna = new List<Method>();
                    listaExterna.Add(mtd);

                    mtd = null;

                    txtMethodName.Focus();
                }
            }
            else
            {

                listaExterna.Remove(mtd);

                string OldMethod = mtd.MethodSignature;

                mtd = new Method();

                mtd.MethodName = pMethodName;
                mtd.ReturnName = pRetornoName;
                mtd.ReturnIsList = pRetornoList;
                mtd.ParamList = this.GeraListaParams(paramList);
                mtd.MethodComent = pCommentName;
                mtd.MethodSignature = MethodSignature;

                this.tvList.Nodes[0].Nodes[pInterface].Nodes[OldMethod].Text = MethodSignature;
                this.tvList.Nodes[0].Nodes[pInterface].Nodes[OldMethod].Name = MethodSignature;

                this.tvList.Nodes[0].Nodes[pInterface].Nodes[mtd.MethodSignature].Tag = mtd;

                this.tvList.Nodes[0].Nodes[pInterface].ExpandAll();

                btnCadMetCancel.Visible = false;
                txtModulo.Enabled = true;
                txtSubModulo.Enabled = true;

                groupInterface.Enabled = true;
                groupListMethods.Enabled = true;

                txtMethodName.Text = string.Empty;
                cbRetornoMetodo.Text = string.Empty;
                cbNameParametroMetodo.Text = string.Empty;
                txtComentarioMetodo.Text = string.Empty;
                rbParametroUnit.Checked = true;
                rbRetornoUnit.Checked = true;
                chkParameter.Checked = false;

                listaExterna.Add(mtd);

                this.mtd = null;

                txtMethodName.Focus();
            }

            txtMethodName.Text = string.Empty;
            cbNameParametroMetodo.Text = string.Empty;
            cbTypeParametroMetodo.Text = string.Empty;
            cbRetornoMetodo.Text = string.Empty;
            txtComentarioMetodo.Text = string.Empty;

            listParams.Nodes[0].Nodes.Clear();

            rbParametroUnit.Checked = true;
            rbRetornoUnit.Checked = true;
            chkParameter.Checked = false;
        }

        private List<Param> GeraListaParams(TreeNodeCollection paramList)
        {
            List<Param> listaRetorno = new List<Param>();

            foreach (TreeNode node in paramList)
            {listaRetorno.Add((Param)node.Tag);}

            return listaRetorno;
        }

        private void tvList_MouseDown(object sender, MouseEventArgs e)
        {
            tvList.SelectedNode = tvList.GetNodeAt(e.X, e.Y);
        }

        private void tvListContext_Opening(object sender, CancelEventArgs e)
        {
            if (tvList.Nodes[0].IsSelected)
                e.Cancel = true;

            if (tvList.SelectedNode == null) 
                e.Cancel = true;
            else
                interfaceAtivaToolStripMenuItem.Visible = (tvList.SelectedNode.Parent == tvList.Nodes[0]);
        }

        private void alterarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tvList.SelectedNode.Parent == tvList.Nodes[0])
            {
                /*Grupo Alterar Interface*/
                btnCadIntCancel.Visible = true;
                txtModulo.Enabled = false;
                txtSubModulo.Enabled = false;

                groupMethods.Enabled = false;
                groupListMethods.Enabled = false;
                
                //INFO
                this.txtInterface.Text = tvList.SelectedNode.Text;
                this.OldInterface = tvList.SelectedNode.Text;
            }
            else
            {
                /*Grupo Alterar Método*/
                btnCadMetCancel.Visible = true;
                txtModulo.Enabled = false;
                txtSubModulo.Enabled = false;

                groupInterface.Enabled = false;
                groupListMethods.Enabled = false;
                
                //INFO
                mtd = ((Method)tvList.SelectedNode.Tag);

                txtMethodName.Text = mtd.MethodName;
                cbRetornoMetodo.Text = mtd.ReturnName;
                txtComentarioMetodo.Text = mtd.MethodComent;

                if (mtd.ReturnIsList)
                    rbRetornoList.Checked = true;
                else
                    rbRetornoUnit.Checked = true;

                this.listParams.Nodes[0].Nodes.Clear();

                foreach (Param param in mtd.ParamList)
                {

                    string paramFormatado = @"Sinacor.Servico.{0}.{1}.Service.DataContract.Request.{2}{3}";

                        if (param.ParameterIsList)
                        {
                            paramFormatado = "List<" + string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, param.ParameterType, "Request") + ">";
                        }
                        else
                        {
                            paramFormatado = string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, param.ParameterType, "Request");
                        }

                        paramFormatado += " " + param.ParameterName;

                        if (param.ParameterIsParameter)
                        {
                            paramFormatado = paramFormatado.Insert(0, "parameter - ");                            
                        }

                    this.listParams.Nodes[0].Nodes.Add(paramFormatado, paramFormatado);
                    this.listParams.Nodes[0].Nodes[paramFormatado].Tag = param;
                }

                cbTypeParametroMetodo.Text = string.Empty;
                cbNameParametroMetodo.Text = string.Empty;
                chkParameter.Checked = false;
                this.listParams.ExpandAll();

            }

        }

        private void deletarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tvList.SelectedNode.Parent == tvList.Nodes[0])
            {
                if (tvList.SelectedNode.GetNodeCount(true) != 0)
                {
                    StringBuilder stb = new StringBuilder();
                    stb.Append("Esta Interface possui metodos cadastrados.");
                    stb.Append(Environment.NewLine);
                    stb.Append("Este processo nao poderá ser desfeito.");
                    stb.Append(Environment.NewLine);
                    stb.Append("Deseja Realmente exclui-la ?");

                    DialogResult result = MessageBox.Show(stb.ToString(), "Confirmação", MessageBoxButtons.YesNo);

                    if (result == DialogResult.Yes)
                    {

                        foreach (TreeNode node in tvList.SelectedNode.Nodes)
                        {
                            listaExterna.Remove((Method)node.Tag);
                        }

                        this.listaInterface.Remove(tvList.SelectedNode.Text);
                        tvList.SelectedNode.Remove();
                    }

                }
                else
                {
                    this.listaInterface.Remove(tvList.SelectedNode.Text);
                    tvList.SelectedNode.Remove();
                }
            }
            else
            {
                this.mtd = null;
                listaExterna.Remove((Method)tvList.SelectedNode.Tag);
                tvList.SelectedNode.Remove();
            }
        }

        private void interfaceAtivaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNodeCollection tnC = tvList.Nodes[0].Nodes;

            foreach (TreeNode node in tnC)
            {
                if (node.BackColor == Color.Yellow)
                    node.BackColor = Color.Transparent;
            }

            this.tvList.SelectedNode.BackColor = Color.Yellow;
            this.txtMethodName.Focus();
        }

        private void btnCadIntCancel_Click(object sender, EventArgs e)
        {
            /*Grupo Alterar Interface*/
            btnCadIntCancel.Visible = false;
            txtModulo.Enabled = true;
            txtSubModulo.Enabled = true;

            groupMethods.Enabled = true;
            groupListMethods.Enabled = true;

            this.txtInterface.Text = string.Empty;
            this.OldInterface = string.Empty;
        }

        private void btnCadMetCancel_Click(object sender, EventArgs e)
        {
            /*Grupo Alterar Método*/
            btnCadMetCancel.Visible = false;
            txtModulo.Enabled = true;
            txtSubModulo.Enabled = true;

            groupInterface.Enabled = true;
            groupListMethods.Enabled = true;

            txtMethodName.Text = string.Empty;
            cbRetornoMetodo.Text = string.Empty;
            cbNameParametroMetodo.Text = string.Empty;
            txtComentarioMetodo.Text = string.Empty;
            rbParametroUnit.Checked = true;
            rbRetornoUnit.Checked = true;
            chkParameter.Checked = false;
            this.listParams.Nodes[0].Nodes.Clear();

            this.mtd = null;
        }

        private void btnProperties_Click(object sender, EventArgs e)
        {
            bool HasEntities = false;

            foreach (Method mtd in listaExterna)
            {
                if (mtd.ParamList.Count != 0)
                {
                    HasEntities = true;
                    break;
                }

                if(mtd.ReturnName != string.Empty)
                {
                    HasEntities = true;
                    break;
                }
            }

            if (HasEntities)
            {
                frmWizardProperties pCad = new frmWizardProperties();

                if (this.listaEntidade == null)
                {
                    this.listaEntidade = new List<Entidade>();
                }
                
                this.FiltraEntidades();

                pCad.listaEntidade = this.listaEntidade;

                if (this.lstEnumerators != null)
                    pCad.lstEnumerators = this.lstEnumerators;

                pCad.ShowDialog();

                this.listaEntidade = pCad.listaEntidade;
                this.lstEnumerators = pCad.lstEnumerators;
            }
            else
                MessageBox.Show("Não existem entidades a serem cadastradas.", "Não existem entidades a serem cadastradas.");
        }

        private void FiltraEntidades()
        {
            //Carrega as Entidades válidas via Lista de Métodos
            List<Entidade> listaInterna = new List<Entidade>();
            foreach (Method mtd in this.listaExterna)
            {
                Entidade entIn = null;
                Entidade entOut = null;

                foreach (Param param in mtd.ParamList)
                {
                    if (param.ParameterIsParameter)
                        entIn = new Entidade(param.ParameterType, Enums.Direction.Parameter);
                    else
                        entIn = new Entidade(param.ParameterType, Enums.Direction.Entrada);

                    var Entity = listaInterna.Find(delegate(Entidade x)
                    {
                        return (x.NomeEntidade == entIn.NomeEntidade && x.Sentido == entIn.Sentido);
                    });

                    if(Entity == null)
                        listaInterna.Add(entIn);    
                }

                if (!string.IsNullOrEmpty(mtd.ReturnName))
                {
                    entOut = new Entidade(mtd.ReturnName, Enums.Direction.Saida);
                    
                    var Entity = listaInterna.Find(delegate(Entidade x)
                    {
                        return (x.NomeEntidade == entOut.NomeEntidade && x.Sentido == entOut.Sentido);
                    });

                    if (Entity == null)
                        listaInterna.Add(entOut);    
                }

            }

            //Verifica se existe alguma na listaEntidade que não esteja na lista interna(Método Removido)
            List<Entidade> listToRemove = new List<Entidade>();
            foreach (Entidade ent in listaEntidade)
            {
                var Entity = listaInterna.Find(delegate(Entidade x)
                {
                    return (x.NomeEntidade == ent.NomeEntidade && x.Sentido == ent.Sentido);
                });

                if (Entity == null)
                    listToRemove.Add((Entidade)ent);

            }

            //Remove da listaEntidade o resultado anterior
            foreach (Entidade ent in listToRemove)
            {
                var Entity = listaEntidade.Find(delegate(Entidade x)
                {
                    return (x.NomeEntidade == ent.NomeEntidade && x.Sentido == ent.Sentido);
                });

                if (Entity != null)
                    listaEntidade.Remove((Entidade)ent);

            }

            //Verifica se existe alguma na listaInterna que não conste na listaEntidade(Método Adicionado)
            List<Entidade> listToAdd = new List<Entidade>();
            foreach (Entidade ent in listaInterna)
            {
                var Entity = listaEntidade.Find(delegate(Entidade x)
                {
                    return (x.NomeEntidade == ent.NomeEntidade && x.Sentido == ent.Sentido);
                });

                if (Entity == null)
                    listToAdd.Add((Entidade)ent);

            }

            //Adiciona na listaEntidade o resultado anterior
            foreach (Entidade ent in listToAdd)
            {
                listaEntidade.Add(ent);
            }
        }

        private void sairToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void salvarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.listaInterface != null && this.listaInterface.Count != 0)
            {
                if (sfdTarget.ShowDialog() == DialogResult.OK)
                {
                    this.SaveSchema(sfdTarget.FileName);
                }
            }
        }

        private void SaveSchema(string pDirection)
        {
            DB dataBase = new DB();
            dataBase.GenerateSchema();
            int SubmoduleId = 0;

            if (listaInterface.Count != 0)
            {
                string[] info = listaInterface[0].Split('.');
                SubmoduleId = dataBase.AddHeader(info[2], info[3]);
            }

            foreach (string interFace in listaInterface)
            {
                string[] info = interFace.Split('.');
                int InterfaceId = dataBase.AddInterface(info[6], SubmoduleId);

                foreach (Method mtd in listaExterna)
                {
                    if (tvList.Nodes[0].Nodes[interFace].Nodes[mtd.MethodSignature] != null)
                    {
                        string intParent = tvList.Nodes[0].Nodes[interFace].Nodes[mtd.MethodSignature].Parent.Text;
                        int MethodId = dataBase.AddMethod(mtd.MethodName, mtd.MethodComent, InterfaceId);

                        foreach (Param param in mtd.ParamList)
                        {
                            dataBase.AddParameter(param.ParameterName, param.ParameterIsList, MethodId, param.ParameterIsParameter, param.ParameterType);   
                        }

                        dataBase.AddReturn(mtd.ReturnName, mtd.ReturnIsList, MethodId);
                    }
                }
            }

            //GravandoEnums
            if (this.lstEnumerators != null && this.lstEnumerators.Count != 0)
            {
                dataBase.GenerateEnumAuxiliarSchema();

                foreach (Enumeradores en in lstEnumerators)
                {
                    int EnumId = dataBase.AddEnum(en.nomeEnum);

                    foreach (object obj in en.itemsEnum)
                    {
                        dataBase.AddEnumItem(obj.ToString(),EnumId);
                    }
                }   
            }

            if (this.listaEntidade == null)
                this.listaEntidade = new List<Entidade>();

            this.FiltraEntidades();

            //GravandoEntidades
            if (this.listaEntidade != null && this.listaEntidade.Count != 0)
            {
                dataBase.GenerateEntidadeAuxiliarSchema();

                foreach (Entidade en in listaEntidade)
                {
                    int EntidadeId = dataBase.AddEntidade(en.NomeEntidade,en.Sentido);

                    foreach (Propriedades prop in en.ListaPropriedades)
                    {
                        dataBase.AddPropriedadeEntidade(prop.NomePropriedade, prop.TipoPropriedade, EntidadeId);
                    }
                }
            }

            dataBase.Authomat.WriteXml(pDirection);
        }

        private void carregarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listaInterface == null || listaInterface.Count == 0)
            {
                if (ofdTarget.ShowDialog() == DialogResult.OK)
                {
                    this.ReadSchema(ofdTarget.FileName,0);
                }
            }
            else
            {
                StringBuilder stb = new StringBuilder();
                stb.Append("Existem informações cadastradas.");
                stb.Append(Environment.NewLine);
                stb.Append("Todas as alterações serão perdidas.");
                stb.Append(Environment.NewLine);
                stb.Append("Deseja sobreescreve-las ?");

                DialogResult result = MessageBox.Show(stb.ToString(), "Confirmação", MessageBoxButtons.YesNo);

                if (result == DialogResult.Yes)
                    if (ofdTarget.ShowDialog() == DialogResult.OK)
                    {
                        this.ReadSchema(ofdTarget.FileName,0);
                    }
            }
        }

        private void ReadSchema(string pDirection, int Source)
        {
            DataSet ds = new DataSet();
            if (Source == 0)
                ds.ReadXml(pDirection);
            else
            {
                System.IO.StringReader sr = new System.IO.StringReader(pDirection.Trim());
                ds.ReadXml(sr);
            }

            //Limpar Campos
            this.ClearFields();

            //Preencher Modulo + SubModulo
            if (ds.Tables.Count != 0 && ds.Tables[0].TableName == "Module")
            {
                if (ds.Tables[0].Rows.Count != 0)
                {
                    txtModulo.Text = ds.Tables[0].Rows[0].ItemArray[1].ToString();

                    if (ds.Tables[1].Rows.Count != 0)
                    {
                        txtSubModulo.Text = ds.Tables[1].Rows[0].ItemArray[2].ToString();
                    }
                }
            }
            //Preencher TreeView Methods
            this.tvList.Nodes.Add("Interface", "Interface");

            //Interface's
            if (ds.Tables[2].Rows.Count != 0)
            {
                foreach (DataRow row in ds.Tables[2].Rows)
                {
                    AddInterface(row.ItemArray[2].ToString());
                }
                
            }

            //Methods

            if (ds.Tables.Count > 3)
            {
                if (ds.Tables[3].Rows.Count != 0)
                {
                    foreach (DataRow row in ds.Tables[3].Rows)
                    {
                        int InterfaceId = Int32.Parse(row.ItemArray[0].ToString());
                        int MethodId = Int32.Parse(row.ItemArray[1].ToString());
                        string MethodName = row.ItemArray[2].ToString();
                        string Comment = row.ItemArray[3].ToString();

                        string InterfaceName = string.Empty;
                        string RetornoName = string.Empty;
                        bool RetornoList = false;
                        string ParameterName = string.Empty;
                        string ParameterType = string.Empty;
                        bool ParameterList = false;
                        bool ParameterIsParameter = false;


                        foreach (DataRow rowInterface in ds.Tables[2].Rows)
                        {
                            if (Int32.Parse(rowInterface.ItemArray[1].ToString()) == InterfaceId)
                            {
                                InterfaceName = rowInterface.ItemArray[2].ToString();
                            }
                        }

                        foreach (DataRow rowRetorno in ds.Tables[4].Rows)
                        {
                            if (Int32.Parse(rowRetorno.ItemArray[0].ToString()) == MethodId)
                            {
                                RetornoName = rowRetorno.ItemArray[2].ToString();
                                RetornoList = Boolean.Parse(rowRetorno.ItemArray[3].ToString());
                            }
                        }

                        TreeView myTempTv = new TreeView();

                        myTempTv.Nodes.Add("params", "params");

                        if (ds.Tables.Count > 5)
                        {
                            foreach (DataRow rowParam in ds.Tables[5].Rows)
                            {
                                if (Int32.Parse(rowParam.ItemArray[0].ToString()) == MethodId)
                                {
                                    Param newParam = new Param();

                                    if (rowParam.ItemArray.Count() > 3)
                                    {
                                        ParameterName = rowParam.ItemArray[2].ToString();
                                        ParameterList = Boolean.Parse(rowParam.ItemArray[3].ToString());
                                        ParameterIsParameter = Boolean.Parse(rowParam.ItemArray[4].ToString());
                                        ParameterType = rowParam.ItemArray[5].ToString();

                                        newParam.ParameterIsList = ParameterList;
                                        newParam.ParameterIsParameter = ParameterIsParameter;
                                        newParam.ParameterName = ParameterName;
                                        newParam.ParameterType = ParameterType;

                                        string paramFormatado = @"Sinacor.Servico.{0}.{1}.Service.DataContract.Request.{2}{3}";

                                        if (newParam.ParameterIsList)
                                        {
                                            paramFormatado = "List<" + string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, ParameterType, "Request") + ">";
                                        }
                                        else
                                        {
                                            paramFormatado = string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, ParameterType, "Request");
                                        }

                                        paramFormatado += " " + ParameterName;

                                        if (ParameterIsParameter)
                                        {
                                            paramFormatado = paramFormatado.Insert(0, "parameter - ");
                                        }

                                        myTempTv.Nodes[0].Nodes.Add(paramFormatado, paramFormatado);
                                        myTempTv.Nodes[0].Nodes[paramFormatado].Tag = newParam;
                                    }
                                }
                            }
                        }

                        AddMethod(this.FormatInterfaceName(InterfaceName), MethodName, RetornoName, RetornoList, myTempTv.Nodes[0].Nodes, Comment);
                    }

                }

                if (ds.Tables["Enums"] != null)
                {
                    if (ds.Tables["Enums"].Rows.Count != 0)
                    {
                        foreach (DataRow rowEnum in ds.Tables["Enums"].Rows)
                        {
                            int EnumId = Int32.Parse(rowEnum.ItemArray[0].ToString());
                            Enumeradores en = new Enumeradores(rowEnum.ItemArray[1].ToString());
                            
                            if (lstEnumerators == null)
                                lstEnumerators = new List<Enumeradores>();
                            
                            lstEnumerators.Add(en);

                            var Enumerador = lstEnumerators.Find(delegate(Enumeradores x)
                            {
                                return (x.nomeEnum == en.nomeEnum);
                            });

                            if (ds.Tables["ItensEnums"] != null)
                            {
                                foreach (DataRow rowEnumItem in ds.Tables["ItensEnums"].Rows)
                                {
                                    if (Int32.Parse(rowEnumItem.ItemArray[0].ToString()) == EnumId)
                                    {
                                        Enumerador.itemsEnum.Add(rowEnumItem.ItemArray[2].ToString());
                                    }
                                }
                            }

                        }
                    }
                }

                if (ds.Tables["Entidade"] != null)
                {
                    if (ds.Tables["Entidade"].Rows.Count != 0)
                    {
                        foreach (DataRow rowEntidade in ds.Tables["Entidade"].Rows)
                        {
                            int EntidadeId = Int32.Parse(rowEntidade.ItemArray[0].ToString());
                            Entidade en = 
                                new Entidade(rowEntidade.ItemArray[1].ToString(),
                                    ((Enums.Direction)System.Enum.Parse(typeof(Enums.Direction), rowEntidade.ItemArray[2].ToString())));

                            /*if (listaEntidade == null)
                                listaEntidade = new List<Entidade>();

                            listaEntidade.Add(en);

                            var Entidade = listaEntidade.Find(delegate(Entidade x)
                            {
                                return (x.NomeEntidade == en.NomeEntidade && x.Sentido == en.Sentido);
                            });*/

                            if (listaEntidade == null)
                                listaEntidade = new List<Entidade>();

                            var Entidade = listaEntidade.Find(delegate(Entidade x)
                            {
                                return (x.NomeEntidade == en.NomeEntidade && x.Sentido == en.Sentido);
                            });

                            if (Entidade == null)
                            {
                                listaEntidade.Add(en);
                                Entidade = en;
                            }

                            if (ds.Tables["PropriedadesEntidade"] != null)
                            {
                                foreach (DataRow rowEntidadePropriedade in ds.Tables["PropriedadesEntidade"].Rows)
                                {
                                    if (Int32.Parse(rowEntidadePropriedade.ItemArray[0].ToString()) == EntidadeId)
                                    {
                                        Propriedades p = new Propriedades(rowEntidadePropriedade.ItemArray[2].ToString(), rowEntidadePropriedade.ItemArray[3].ToString());

                                        Entidade.ListaPropriedades.Add(p);
                                    }
                                }
                            }
                        }
                    }
                }
                
            }

        }

        private string FormatInterfaceName(string InterfaceName)
        {
            string strInterface = @"Sinacor.Servico.{0}.{1}.Service.ServiceContract.";

            strInterface = string.Format(strInterface, txtModulo.Text, txtSubModulo.Text);

            return strInterface += InterfaceName;
        }

        private void ClearFields()
        {
            txtModulo.Text = string.Empty;
            txtSubModulo.Text = string.Empty;
            txtInterface.Text = string.Empty;
            txtMethodName.Text = string.Empty;
            cbRetornoMetodo.Text = string.Empty;
            cbNameParametroMetodo.Text = string.Empty;
            txtComentarioMetodo.Text = string.Empty;
            tvList.Nodes.Clear();
            rbRetornoUnit.Checked = true;
            rbParametroUnit.Checked = true;
            chkParameter.Checked = false;

            listaInterface = null; 
            listaExterna = null;
            listaEntidade = null;
            lstEnumerators = null;
            listParams.Nodes[0].Nodes.Clear();

        }

        private void btnAction_Click(object sender, EventArgs e)
        {
            if (this.listaInterface == null || this.listaInterface.Count == 0)
            {
                MessageBox.Show("Não existem dados para geração.", "Não existem dados para geração.");
                return;
            }
            else
            {
                string idFolder = string.Empty;

                if (fbdStruct.ShowDialog() == DialogResult.OK)
                {
                    idFolder = this.GenerateStruct(fbdStruct.SelectedPath);
                }

                StringBuilder stb = new StringBuilder();

                stb.Append("Código Gerado com Sucesso.");
                stb.Append(Environment.NewLine);
                stb.Append("Deseja gerar o Arquivo de Especificação Técnica ?");
                stb.Append(Environment.NewLine);

                if (MessageBox.Show(stb.ToString(), "Confirmação", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    if (ofdEA.ShowDialog() == DialogResult.OK)
                    {
                        this.GenerateEA(ofdEA.FileName, fbdStruct.SelectedPath + "\\" + idFolder);
                    }
                }
            }
        }

        private void GenerateEA(string pFileName, string pClassPath)
        {
            EA.RepositoryClass eaFile = new EA.RepositoryClass();

            try
            {
                eaFile.OpenFile(pFileName);

                EA.ProjectClass eaProject = new EA.ProjectClass();
                eaProject.LoadProject(pFileName);
                eaProject.ImportDirectory(eaFile.GetPackageByID(1).PackageGUID, "C#", pClassPath, "");
                eaFile.CloseFile();

            }
            catch (Exception ex)
            {
                eaFile.CloseFile();
                MessageBox.Show(ex.Message, "Informação!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private string GenerateStruct(string pTarget)
        {
            string folderRootName = this.listaInterface[0].Split('.')[2]  + "." + this.listaInterface[0].Split('.')[3];
            DirectoryInfo dir = null;
            dir = new DirectoryInfo(pTarget);

            dir.CreateSubdirectory(folderRootName);

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName);

            dir.CreateSubdirectory("Servico");

            dir.CreateSubdirectory("UI");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "UI");

            dir.CreateSubdirectory("Communication");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "UI" + "\\" + "Communication");
            dir.CreateSubdirectory("Translator");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "UI" + "\\" + "Communication" + "\\" + "Translator");
            dir.CreateSubdirectory("DataContractToModel");
            dir.CreateSubdirectory("ModelToDataContract");

            dir = dir.Parent.Parent;

            dir.CreateSubdirectory("Model");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "UI" + "\\" + "Model");
            dir.CreateSubdirectory("Enum");
            dir.CreateSubdirectory("Parameter");

            dir = dir.Parent;

            dir.CreateSubdirectory("Presenter");
            dir.CreateSubdirectory("View");
            
            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico");

            dir.CreateSubdirectory("BusinessEntity");
            dir.CreateSubdirectory("BusinessLogic");
            dir.CreateSubdirectory("ResourceAccess");
            dir.CreateSubdirectory("Service");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico" + "\\" + "BusinessEntity");

            dir.CreateSubdirectory("Enum");
            dir.CreateSubdirectory("Parameter");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico" + "\\" + "Service");

            dir.CreateSubdirectory("DataContract");
            dir.CreateSubdirectory("ServiceContract");
            dir.CreateSubdirectory("ServiceImplementation");

            foreach (string str in this.listaInterface)
            {
                //SERVICO
                Generate.GenerateInterfaceFile(dir, str, this.listaExterna, tvList);
                Generate.GenerateImplementationFile(dir, str, this.listaExterna,tvList);
                Generate.GenerateMethodAssignFiles(dir, str, this.listaExterna, tvList, Enums.OrigemEnum.BusinessLogic);
                Generate.GenerateMethodAssignFiles(dir, str, this.listaExterna, tvList, Enums.OrigemEnum.ResourceAccess);

                //UI
                Generate.GenerateCommunicationFile(dir, str, this.listaExterna, tvList);
                Generate.GeneratePresenterFile(dir, str, this.listaExterna, tvList);
            }

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico" + "\\" + "Service" + "\\" + "DataContract");

            dir.CreateSubdirectory("Enum");
            dir.CreateSubdirectory("Request");
            dir.CreateSubdirectory("Response");


            List<Entidade> entRequest = new List<Entidade>();
            List<Entidade> entParameter = new List<Entidade>();
            List<Entidade> entResponse = new List<Entidade>();

            if (this.listaEntidade == null)
                this.listaEntidade = new List<Entidade>();
            

            foreach (Entidade ent in this.listaEntidade)
            {
                switch (ent.Sentido)
                {
                    case Enums.Direction.Entrada:
                        {
                            if (!entRequest.Contains(ent))
                                entRequest.Add(ent);
                        }
                        break;
                    case Enums.Direction.Saida:
                        {
                            if(!entResponse.Contains(ent))
                                entResponse.Add(ent);
                        }
                        break;
                    case Enums.Direction.Parameter:
                        {
                            if (!entParameter.Contains(ent))
                                entParameter.Add(ent);
                        }
                        break;
                    default:
                        break;
                }
            }

            //Data Contracts - OK
            Generate.GenerateDCFiles(entRequest, dir,0, txtModulo.Text, txtSubModulo.Text);
            Generate.GenerateDCFiles(entParameter, dir, 0, txtModulo.Text, txtSubModulo.Text);
            Generate.GenerateDCFiles(entResponse, dir, 1, txtModulo.Text, txtSubModulo.Text);
            Generate.GenerateEnumFiles(this.lstEnumerators, dir, txtModulo.Text, txtSubModulo.Text, Enums.OrigemEnum.DataContract);
            
            //Business Entity
            List<Entidade> listParameter = null;
            List<Entidade> listBusinessEntity = this.FiltrarEntidades(out listParameter);
            Generate.GenerateBEFiles(listBusinessEntity, dir, txtModulo.Text, txtSubModulo.Text,false);
            Generate.GenerateBEFiles(listParameter, dir, txtModulo.Text, txtSubModulo.Text,true);
            Generate.GenerateEnumFiles(this.lstEnumerators, dir, txtModulo.Text, txtSubModulo.Text, Enums.OrigemEnum.BusinessEntity);

            //UI/Model
            Generate.GenerateModelFiles(listBusinessEntity, dir, txtModulo.Text, txtSubModulo.Text, false);
            Generate.GenerateModelFiles(listParameter, dir, txtModulo.Text, txtSubModulo.Text, true);
            Generate.GenerateEnumFiles(this.lstEnumerators, dir, txtModulo.Text, txtSubModulo.Text, Enums.OrigemEnum.Model);

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico" + "\\" + "Service" + "\\" + "ServiceImplementation");

            dir.CreateSubdirectory("Translator");

            dir = new DirectoryInfo(pTarget + "\\" + folderRootName + "\\" + "Servico" + "\\" + "Service" + "\\" + "ServiceImplementation" + "\\" + "Translator");

            dir.CreateSubdirectory("BusinessEntityToDataContract");
            dir.CreateSubdirectory("DataContractToBusinessEntity");

            foreach (string str in this.listaInterface)
            {
                string interna = str.Split('.')[6].Substring(1);
                Generate.GenerateBETranslatorFile(dir, interna, str, this.listaExterna, tvList);
                Generate.GenerateDCTranslatorFile(dir, interna, str, this.listaExterna, tvList);
                Generate.GenerateCommunicationTranslatorFile(dir, interna, str, this.listaExterna, tvList);
            }

            return folderRootName;

        }

        private List<Entidade> FiltrarEntidades(out List<Entidade> listaParameter)
        {
            List<Entidade> listInterna = new List<Entidade>();
            List<Entidade> listParameterInterna = new List<Entidade>();

            foreach (Entidade ent in this.listaEntidade)
            {
                if (ent.Sentido != Enums.Direction.Parameter)
                {
                    var Entity = listInterna.Find(delegate(Entidade x)
                        {
                            return (x.NomeEntidade == ent.NomeEntidade);
                        });

                    if (Entity == null)
                    {
                        listInterna.Add(ent);
                    }

                }
                else
                {
                    listParameterInterna.Add(ent);
                }
            }

            listaParameter = listParameterInterna;
            return listInterna;

        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(cbNameParametroMetodo.Text))
            { 
                
            }
            else
                if (string.IsNullOrEmpty(cbTypeParametroMetodo.Text))
                {

                }
                else
                {
                    string paramFormatado = @"Sinacor.Servico.{0}.{1}.Service.DataContract.Request.{2}{3}";

                        if (rbParametroList.Checked)
                        {
                            paramFormatado = "List<" + string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, cbTypeParametroMetodo.Text, "Request") + ">";
                        }
                        else
                        {
                            paramFormatado = string.Format(paramFormatado, txtModulo.Text, txtSubModulo.Text, cbTypeParametroMetodo.Text, "Request");
                        }

                        paramFormatado += " " + cbNameParametroMetodo.Text;

                        if (chkParameter.Checked)
                        {
                            paramFormatado = paramFormatado.Insert(0, "parameter - ");                            
                        }

                    
                    Param newParam = new Param();
                    
                    if (rbParametroList.Checked)
                        { newParam.ParameterIsList = true; }
                        else
                        { newParam.ParameterIsList = false; }
                        
                    newParam.ParameterIsParameter = chkParameter.Checked;
                    newParam.ParameterName = cbNameParametroMetodo.Text;
                    newParam.ParameterType = cbTypeParametroMetodo.Text;

                    this.listParams.Nodes[0].Nodes.Add(paramFormatado,paramFormatado);
                    this.listParams.Nodes[0].Nodes[paramFormatado].Tag = newParam;
                    
                    //Limpando Controles
                    cbTypeParametroMetodo.Text = string.Empty;
                    cbNameParametroMetodo.Text = string.Empty;
                    chkParameter.Checked = false;
                    this.listParams.ExpandAll();
                    cbTypeParametroMetodo.Focus();
                }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (this.listParams.SelectedNode != null && this.listParams.SelectedNode != this.listParams.Nodes[0])
                this.listParams.Nodes.Remove(this.listParams.SelectedNode);
        }

        private void crudToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmCrudData formCrud = new frmCrudData();
            //Paulo Silva - 14/05/2010
            //Atribuindo o nome do módulo e sub-modulo na tela de CRUD, já informados na tela de WIZARD
            formCrud.NomeModulo = txtModulo.Text;
            formCrud.NomeSubModulo = txtSubModulo.Text;

            formCrud.ShowDialog();

            if (formCrud.Enviado)
            {
                string myXml = Core.crud.xmlCrud;

                //Modulo
                myXml = myXml.Replace("@@Module", formCrud.Modulo);

                //SubModulo
                myXml = myXml.Replace("@@SubModule", formCrud.SubModulo);

                //Entidade
                myXml = myXml.Replace("@@Entidade", formCrud.Entidade);

                //EntidadePlural
                myXml = myXml.Replace("@@PluralEntidade", formCrud.EntidadePlural);

                this.ReadSchema(myXml, 1);
            }
            

        }

        private void cbRetorno_Enter(object sender, EventArgs e)
        {
            LoadReturnSource();
        }

        private void cbTypeParametroMetodo_Enter(object sender, EventArgs e)
        {
            LoadParamTypeSource();
        }

        private void cbNameParametroMetodo_Enter(object sender, EventArgs e)
        {
            LoadParamNameSource();
        }
    }
}
